/**
 * @file      ac_tlm_bit_count.cpp
 * @author    Grupo 04
 * 
 * @brief     Implements a ac_tlm bit_bit_count.
 */

//////////////////////////////////////////////////////////////////////////////

#ifndef AC_TLM_BIT_COUNT_H_
#define AC_TLM_BIT_COUNT_H_

//////////////////////////////////////////////////////////////////////////////

// Standard includes
// SystemC includes
#include <systemc>
// ArchC includes
#include "ac_tlm_protocol.H"

//////////////////////////////////////////////////////////////////////////////

// using statements
using tlm::tlm_transport_if;

//////////////////////////////////////////////////////////////////////////////

/// Namespace to isolate memory from ArchC
namespace user
{

/// A TLM bit counter
class ac_tlm_bit_count :
  public sc_module,
  public ac_tlm_transport_if // Using ArchC TLM protocol
{
public:

  /// Exposed port with ArchC interface
  sc_export< ac_tlm_transport_if > target_export;
  /// Internal write
  ac_tlm_rsp_status writem( const uint32_t & );
  /// Internal read
  ac_tlm_rsp_status readm( uint32_t & );
  
  /**
   * Implementation of TLM transport method that
   * handle packets of the protocol doing apropriate actions.
   * This method must be implemented (required by SystemC TLM).
   * @param request is a received request packet
   * @return A response packet to be send
  */
  ac_tlm_rsp transport( const ac_tlm_req &request ) {

    ac_tlm_rsp response;

    switch( request.type ) {
    case READ :     // Packet is a READ one
      #ifdef DEBUG  // Turn it on to print transport level messages
	cout << "Transport WRITE at " << request.addr << " value ";
	cout << response.data << endl;
      #endif
      response.status = readm( response.data );
      break; 
    case WRITE:     // Packet is a WRITE
      #ifdef DEBUG
	cout << "Transport READ at " << request.addr << " value ";
	cout << request.data << endl;
      #endif
      response.status = writem( request.data );
      break;
    default :
      response.status = ERROR;
      break; 
    }

    return response;
  }


  /** 
   * Default constructor.
   */
  ac_tlm_bit_count( sc_module_name module_name);


  #include <limits.h>
  static int bit_count(long int i)
  {
      i = ((i & 0xAAAAAAAAL) >>  1) + (i & 0x55555555L);
      i = ((i & 0xCCCCCCCCL) >>  2) + (i & 0x33333333L);
      i = ((i & 0xF0F0F0F0L) >>  4) + (i & 0x0F0F0F0FL);
      i = ((i & 0xFF00FF00L) >>  8) + (i & 0x00FF00FFL);
      i = ((i & 0xFFFF0000L) >> 16) + (i & 0x0000FFFFL);
      return (int)i;
  }

private:
  uint32_t valor;

};

};

#endif //AC_TLM_BIT_COUNT_H_
